package com.magenta.maxoptra.yournavigation.org;

import com.magenta.maxoptra.gis.commons.StringUtils;
import com.magenta.maxoptra.dto.GeoLocationRecord;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

/**
 * Project: Santa-cruz
 * Author:  Irina Isaeva
 * Created: 09.06.12 11:10
 * <p/>
 * Copyright (c) 1999-2012 Magenta Corporation Ltd. All Rights Reserved.
 * Magenta Technology proprietary and confidential.
 * Use is subject to license terms.
 * <p/>
 * $Id$
 */
public class YourNavigationWS {

    private static final String UK = "UK";
    private static final String TAG1_DOCUMENT = "Document";
    private static final String TAG2_FOLDER = "Folder";
    private static final String TAG3_LINESTRING = "LineString";
    private static final String TAG4_COORDINATES = "coordinates";
    private static final String POINTS_DELIMITER = "\n";
    private static final String COORDINATES_DELIMITER = ",";


    private static YourNavigationWS instanse = null;

    public static YourNavigationWS getInstance() {
        if (instanse == null) {
            instanse = new YourNavigationWS();
        }
        return instanse;
    }

    private YourNavigationWS() {
    }


    private InputStream getStream(java.net.Proxy proxy, String requestString) throws IOException {
        URL url = new URL(requestString);
        URLConnection urlConnection = null;
        if (proxy != null) {
            urlConnection = url.openConnection(proxy);
        } else {
            urlConnection = url.openConnection();
        }
        return urlConnection.getInputStream();
    }


    public TrafficRoad getDistance(java.net.Proxy proxy, String url, Double x1, Double y1, Double x2, Double y2) throws XmlPullParserException, IOException {
        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        factory.setNamespaceAware(true);
        XmlPullParser xpp = factory.newPullParser();

        boolean distance;
        boolean time;

        TrafficRoad trafficRoad = new TrafficRoadImpl();
        distance = false;
        time = false;
        InputStream in = getStream(proxy, url);
        xpp.setInput(in, "UTF-8");
        int eventType = xpp.next();
        while ((trafficRoad.emptyDistance() || trafficRoad.emptyTime()) && eventType != XmlPullParser.END_DOCUMENT) {
            switch (eventType) {
                case (XmlPullParser.START_TAG): {
                    if (xpp.getName().equalsIgnoreCase("distance")) {
                        distance = true;
                    }
                    if (xpp.getName().equalsIgnoreCase("traveltime")) {
                        time = true;
                    }
                    break;
                }
                case (XmlPullParser.TEXT): {
                    if (distance) {
                        trafficRoad.setDistance(xpp.getText());
                    }
                    if (time) {
                        trafficRoad.setTime(xpp.getText());
                    }
                    break;
                }
                case (XmlPullParser.END_TAG): {
                    if (xpp.getName().equalsIgnoreCase("distance")) {
                        distance = false;
                    }
                    if (xpp.getName().equalsIgnoreCase("traveltime")) {
                        time = false;
                    }
                    break;
                }
            }
            eventType = xpp.next();
        }
        in.close();
        return trafficRoad;
    }

    public List<GeoLocationRecord> extractRoutePointsFromRequest(String requestResult)
            throws IOException, ParserConfigurationException, SAXException, XmlPullParserException {

        List<GeoLocationRecord> result = new ArrayList<GeoLocationRecord>();
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();

        InputStream xmlStream = new ByteArrayInputStream(requestResult.getBytes("UTF-8"));
        DocumentBuilder docBuilder = domFactory.newDocumentBuilder();
        Document dom = docBuilder.parse(xmlStream);

        // root element (i.e. <shipments>)
        NodeList document = dom.getDocumentElement().getElementsByTagName(TAG1_DOCUMENT);
        if (document != null) {
            for (int i = 0; i < document.getLength(); i++) {
                Element el = (Element) document.item(i);
                NodeList folder = el.getElementsByTagName(TAG2_FOLDER);
                if (folder != null) {
                    for (int f = 0; f < folder.getLength(); f++) {
                        Element placemark = (Element) folder.item(f);
                        NodeList lineString = placemark.getElementsByTagName(TAG3_LINESTRING);
                        if (lineString != null) {
                            for (int ls = 0; ls < lineString.getLength(); ls++) {
                                Element lsElement = (Element) lineString.item(ls);
                                NodeList coordinates = lsElement.getElementsByTagName(TAG4_COORDINATES);
                                if (coordinates != null) {
                                    for (int c = 0; c < coordinates.getLength(); c++) {
                                        Element coordinatesItem = (Element) coordinates.item(0);
                                        Node firstChild = coordinatesItem.getFirstChild();
                                        String coordinatesString = firstChild.getNodeValue();
                                        if (StringUtils.isNotEmpty(coordinatesString)) {
                                            String[] splitted = coordinatesString.trim().split(POINTS_DELIMITER);
                                            for (String coordsStr : splitted) {
                                                String[] coords = coordsStr.split(COORDINATES_DELIMITER);
                                                String lon = coords[0];
                                                String lat = coords[1];
                                                GeoLocationRecord record = new GeoLocationRecord(lon, lat);
                                                result.add(record);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return result;
    }
}
